/*
 * ExternalSort_gtest.h
 *
 *  Created on: Dec 15, 2012
 *      Author: bruno
 */

#ifndef EXTERNALSORT_GTEST_H_
#define EXTERNALSORT_GTEST_H_

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cassert>
#include <cstdlib>
#include <sstream>
#include "../physical_layer/file_system/TermOccurrence.h"
#include "../logic_layer/external_sort/tools/Heap.h"
#include "../logic_layer/external_sort/ExternalSort.h"

template<typename T>
void printArray(T array[], size_t size) {
	for (size_t i = 0; i < size; i++) {
		cout << array[i] << " ";
	}
	cout << endl;
}

int comparator(int i1, int i2) {
	return i1 - i2;
}

void assertAndPrintPoppedItems(Heap<int, comparator> &heap, int expected[]) {
	size_t heapCount = heap.lenght();
	for (size_t i = 0; i < heapCount; i++) {
		int reg = heap.popItem();
		cout << reg << " ";
		ASSERT_TRUE(reg == expected[i]);
	}
	cout << endl;
}

void assertAndPrintItems(unsigned int i, int expected[], int reg) {
	cout << reg << " ";
	ASSERT_TRUE(reg == expected[i]);
}

class ExternalSortTestFixture: public ::testing::Test
{
public:

	std::string m_filename;

	ExternalSortTestFixture() {
		const ::testing::TestInfo* const test_info =
				::testing::UnitTest::GetInstance()->current_test_info();

		std::string filename(test_info->name());
		filename.append(".");
		filename.append(test_info->test_case_name());
		filename.append(".tmp");

		m_filename = filename;
	}

	virtual ~ExternalSortTestFixture() {
	}

	void SetUp() {
	}

	void TearDown() {
	}

	const char* getFileNameForTest() {
		return m_filename.c_str();
	}

};

TEST_F ( ExternalSortTestFixture, HeapTest )
{
	cout << "___Heap Test___" << endl;

	int input[] = { 10, 56, 2, 7, 6, 4, 12 };

	printArray(input, 7);

	cout << "Pop Test" << endl;
	{
		Heap<int, comparator> heap(7);
		int expected[] = { 2, 4, 6, 7, 10, 12, 56 };

		for (size_t i = 0; i < 7; i++) {
			heap.loadItem(input[i]);
		}

		heap.heapify();
		cout << "Output:" << endl;

		assertAndPrintPoppedItems(heap, expected);
	}

	cout << "PushAndPop Test" << endl;
	{
		Heap<int, comparator> heap(7);
		int reg = -1;
		for (size_t i = 0; i < 4; i++) {
			heap.loadItem(input[i]);
		}
		heap.heapify();
		cout << "Output:" << endl;
		{
			int expected[] = { 2, 6 };
			for (size_t i = 4; i < 6; i++) {
				reg = heap.pushAndPopItem(input[i]);
				assertAndPrintItems(i - 4, expected, reg);
			}
		}
		cout << "Rest:" << endl;
		{
			int expected[] = { 4, 7, 10, 56 };
			assertAndPrintPoppedItems(heap, expected);
		}
	}

	cout << "Freeze Test" << endl;
	{
		Heap<int, comparator> heap(3);
		int reg = -1;
		for (size_t i = 0; i < 3; i++) {
			heap.loadItem(input[i]);
		}
		heap.heapify();
		cout << "Output Freeze:" << endl;
		{
			int expected[] = { 2, 10, 56 };
			for (size_t i = 3; i < 6; i++) {
				reg = heap.freezeItem(input[i]);
				assertAndPrintItems(i - 3, expected, reg);
			}
		}
		cout << endl << "UnFreezed Items:" << endl;
		{
			int expected[] = { 4, 6, 7 };
			heap.unfreezeItems();
			assertAndPrintPoppedItems(heap, expected);
		}
	}
}



#endif /* EXTERNALSORT_GTEST_H_ */
